package top.yuanao.im.webSocket;


import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSONObject;
import top.yuanao.im.entity.IMUser;
import top.yuanao.im.entity.Mess;
import top.yuanao.im.util.SocketUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;

/**
 * IM22k的主要WebSocket链接地址,
 * 二级地址{user}会被解析为用户名,传输到open()方法的参数里
 *
 * @author Yuanao
 * @CreateDate 2021/10/21 11:45
 */
@ServerEndpoint(value="/websocket/{user}")
public class MainWebSocket {


    /**
     * 建立连接的时候执行
     * @param user 连接是使用的用户名
     * @param session 连接创建的session
     * @throws IOException
     */
    @OnOpen
    public void onOpen(@PathParam("user") String user,Session session) throws IOException{
        System.out.println("新连接：" + user);

        /*根据新的WebSocket session 和用户名创建新的IMUser对象,然后将该对象添加到用户池中*/
        IMUser imUser = new IMUser(session, user);
        SocketUtils.addUser(imUser);

        //像所有人发送网络提醒
        Mess mess = new Mess(200, "欢迎 <span style='color:yellow;'> " + user + " </span>加入聊天室", "<span style='color:red;'>系统提示>>></span>",
                DateTime.now().toDateStr(), SocketUtils.getCurrentUserCount(), SocketUtils.getAllUserName());

        SocketUtils.sendAllUser(JSONObject.toJSONString(mess));
    }

    /**
     * 当WebSocket连接关闭的时候执行的方法
     * @param session WebSocket连接对象session
     */
    @OnClose
    public void onClose(Session session){
        //更具session获取到对应的IMUser
        IMUser user = SocketUtils.getUserBySession(session);
        if (user == null) {
            return; //用户库里没有的时候直接结束函数
        }

        //在用户列表里删除当前关闭的用户
        SocketUtils.removeUser(user);

        System.out.println(user.getName() +  " 连接关闭");

        /*做一次全用户查询,为了刷新前端的数据显示*/
        Set<IMUser> users = SocketUtils.getUsers();

        System.out.println("当前剩余:" +users.size() + " " + users );

        //发送下线提示,给所有用户,提醒其刷新
        Mess mess = new Mess(-1, "<span style='color:yellow'>" + user.getName() + " </span> 已下线", "系统提醒",
                DateTime.now().toDateStr(), SocketUtils.getCurrentUserCount(), SocketUtils.getAllUserName());
        SocketUtils.sendAllUser(JSONObject.toJSONString(mess));

    }

    /**
     * 接受到消息的时候执行
     * 当接收到用户传来的消息的时候,将该消息分装成Mess对象,
     * 然后将该对象转发给所有用户
     * @param message 用户发送过来的消息
     * @param session WebSocket的链接session
     * @throws IOException IO异常,因为要用到网络输出io
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {

        IMUser userBySession = SocketUtils.getUserBySession(session);

        if (userBySession == null) {
            System.err.print("得到了一条消息,但没有对应的用户");
            System.err.println(session);
            System.err.println(message);
            System.err.println("******************************");
            return;
        }

        //创建消息体实体类
        Mess mess = new Mess(1, message, userBySession.getName(),
                DateTime.now().toDateStr(), SocketUtils.getCurrentUserCount(), SocketUtils.getAllUserName());
        SocketUtils.sendAllUser(JSONObject.toJSONString(mess));

        System.out.println(userBySession.getName() + "发送了消息:" + message);

    }

    /**
     * 链接出现错误的时候执行该方法
     * @param session 链接session对象
     * @param error 异常信息
     */
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("错误:" + session);
        error.printStackTrace();
    }
}
